/**
 * @fileOverview resize
 * node resize , edge resize
 * @author huangtonger@aliyun.com
 */

const Util = require('../util');
const Global = require('../global');
const Mixin = {};

function clearControlPoints(item) {
  if (item.controlPointShapes) {
    Util.each(item.controlPointShapes, shape => {
      shape.remove();
    });
  }
  item.controlPointShapes = [];
  item.isControlPointShow = false;
}

function showControlPoints(item) {
  if (item.controlPointShapes) {
    Util.each(item.controlPointShapes, shape => {
      shape.show();
    });
  }
  item.isControlPointShow = true;
}

function hideControlPoints(item) {
  if (item.controlPointShapes) {
    Util.each(item.controlPointShapes, shape => {
      shape.hide();
    });
  }
  item.isControlPointShow = false;
}

function drawNodeController(node, group) {
  const box = node.getBBox();
  const points = [
    {
      x: box.minX,
      y: box.minY
    },
    {
      x: box.maxX,
      y: box.minY
    },
    {
      x: box.minX,
      y: box.maxY
    },
    {
      x: box.maxX,
      y: box.maxY
    }
  ];
  clearControlPoints(node);
  const shape = group.addShape('rect', {
    attrs: Util.mix({}, Global.nodeSelectedBoxStyle, {
      symbol: 'square',
      x: box.minX,
      y: box.minY,
      width: box.maxX - box.minX,
      height: box.maxY - box.minY
    })
  });
  node.controlPointShapes.push(shape);
  Util.each(points, point => {
    const shape = group.addShape('marker', {
      attrs: Util.mix({}, Global.nodeControlPointStyle, {
        symbol: 'square',
        x: point.x,
        y: point.y
      }),
      freezePoint: {
        x: point.x,
        y: point.y
      },
      item: node
    });
    node.controlPointShapes.push(shape);
  });
}

function drawEdgeController(edge, group) {
  const keyShape = edge.getKeyShape();
  const path = keyShape.attr('path');
  const firstSegment = path[0];
  const fl = firstSegment.length;
  const lastSegment = path[path.length - 1];
  const ll = lastSegment.length;
  const points = [
    { x: firstSegment[fl - 2], y: firstSegment[fl - 1] },
    { x: lastSegment[ll - 2], y: lastSegment[ll - 1] }
  ];
  const model = edge.getModel();
  clearControlPoints(edge);
  Util.each(points, (point, index) => {
    const shape = group.addShape('marker', {
      attrs: Util.mix({}, Global.edgeControlPointStyle, {
        x: point.x,
        y: point.y
      }),
      freezePoint: {
        x: point.x,
        y: point.y
      },
      item: edge
    });
    shape.eventPreFix = 'edgeControlPoint';
    shape.getSourcePoint = () => {
      return points[0];
    };
    shape.getTargetPoint = () => {
      return points[points.length - 1];
    };
    shape.getItem = () => {
      return edge;
    };
    shape.isSourceEndPoint = () => {
      return model.source && index === 0;
    };
    shape.isTargetEndPoint = () => {
      return model.target && index === (points.length - 1);
    };
    edge.controlPointShapes.push(shape);
  });
}

Mixin.INIT = '_initResize';

Mixin.CFG = {
  /**
   * @type {boolean}
   */
  nodeResizeable: false,
  /**
   * @type {boolean}
   */
  edgeResizeable: true
};
Mixin.AUGMENT = {
  _initResize() {
    const graph = this.get('_graph');
    const nodeResizeable = this.get('nodeResizeable');
    const edgeResizeable = this.get('edgeResizeable');
    if (nodeResizeable) {
      graph.on('afteritemdraw', ev => {
        if (ev.item.type === 'node' && ev.item.isVisible()) {
          this.drawControlPoints(ev.item);
        }
      });
    }
    if (edgeResizeable) {
      graph.on('afteritemdraw', ev => {
        if (ev.item.type === 'edge' && ev.item.isVisible()) {
          this.drawControlPoints(ev.item);
        }
      });
    }
    graph.on('afteritemhide', ev => {
      ev.item.isControlPointShow && hideControlPoints(ev.item);
    });
    graph.on('afteritemshow', ev => {
      !ev.item.isControlPointShow && showControlPoints(ev.item);
    });
    graph.on('beforeitemdestroy', ev => {
      ev.item.isControlPointShow && clearControlPoints(ev.item);
    });
  },
  drawControlPoints(item) {
    const graph = this.get('_graph');
    const rootGroup = graph.getRootGroup();
    const nodeResizeable = this.get('nodeResizeable');
    const edgeResizeable = this.get('edgeResizeable');
    if (item.type === 'node') {
      nodeResizeable && drawNodeController(item, rootGroup);
    } else if (item.type === 'edge') {
      edgeResizeable && drawEdgeController(item, rootGroup);
    }
    item.isControlPointShow = true;
  }
};
module.exports = Mixin;
